import { useState, useEffect, useRef, useCallback } from 'react';

/**
 * 缓存项接口
 */
interface CacheItem<T> {
  data: T;
  timestamp: number;
  ttl: number; // Time to live in milliseconds
}

/**
 * 客户端缓存Hook
 */
export const useCache = <T>(
  key: string,
  fetchFn: () => Promise<T>,
  options: {
    ttl?: number; // 缓存时间（毫秒）
    enabled?: boolean;
    staleWhileRevalidate?: boolean;
  } = {}
) => {
  const {
    ttl = 5 * 60 * 1000, // 默认5分钟
    enabled = true,
    staleWhileRevalidate = true
  } = options;

  const [data, setData] = useState<T | null>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<Error | null>(null);
  const cacheRef = useRef<Map<string, CacheItem<T>>>(new Map());

  // 检查缓存是否有效
  const isCacheValid = useCallback((cacheItem: CacheItem<T>): boolean => {
    return Date.now() - cacheItem.timestamp < cacheItem.ttl;
  }, []);

  // 从缓存获取数据
  const getFromCache = useCallback((cacheKey: string): T | null => {
    const cachedItem = cacheRef.current.get(cacheKey);
    if (cachedItem && isCacheValid(cachedItem)) {
      return cachedItem.data;
    }
    return null;
  }, [isCacheValid]);

  // 设置缓存
  const setCache = useCallback((cacheKey: string, value: T, customTtl?: number) => {
    cacheRef.current.set(cacheKey, {
      data: value,
      timestamp: Date.now(),
      ttl: customTtl || ttl
    });
  }, [ttl]);

  // 清除缓存
  const clearCache = useCallback((cacheKey?: string) => {
    if (cacheKey) {
      cacheRef.current.delete(cacheKey);
    } else {
      cacheRef.current.clear();
    }
  }, []);

  // 获取数据
  const fetchData = useCallback(async (forceRefresh = false) => {
    if (!enabled) return;

    try {
      setLoading(true);
      setError(null);

      // 如果不强制刷新，先尝试从缓存获取
      if (!forceRefresh) {
        const cachedData = getFromCache(key);
        if (cachedData && !staleWhileRevalidate) {
          setData(cachedData);
          setLoading(false);
          return;
        }
      }

      // 如果启用了staleWhileRevalidate且有缓存数据，先返回缓存数据
      if (staleWhileRevalidate && !forceRefresh) {
        const cachedData = getFromCache(key);
        if (cachedData) {
          setData(cachedData);
        }
      }

      // 获取最新数据
      const freshData = await fetchFn();
      setCache(key, freshData);
      setData(freshData);
    } catch (err) {
      setError(err instanceof Error ? err : new Error('Unknown error'));

      // 如果没有缓存数据，抛出错误
      if (!data) {
        throw err;
      }
    } finally {
      setLoading(false);
    }
  }, [key, fetchFn, enabled, getFromCache, setCache, staleWhileRevalidate, data]);

  // 自动获取数据
  useEffect(() => {
    if (enabled) {
      fetchData();
    }
  }, [fetchData, enabled]);

  return {
    data,
    loading,
    error,
    refetch: () => fetchData(true),
    clearCache: () => clearCache(key),
    invalidateCache: clearCache
  };
};

/**
 * 本地存储缓存Hook
 */
export const useLocalStorageCache = <T>(
  key: string,
  initialValue: T,
  options: {
    ttl?: number;
    serializer?: (value: T) => string;
    deserializer?: (value: string) => T;
  } = {}
) => {
  const {
    ttl = 24 * 60 * 60 * 1000, // 默认24小时
    serializer = JSON.stringify,
    deserializer = JSON.parse
  } = options;

  const [data, setData] = useState<T>(() => {
    try {
      const item = localStorage.getItem(key);
      if (item) {
        const parsed = deserializer(item);
        // 检查是否过期
        if (parsed.timestamp && Date.now() - parsed.timestamp < ttl) {
          return parsed.data;
        } else {
          localStorage.removeItem(key);
        }
      }
    } catch (error) {
      console.error('Failed to read from localStorage:', error);
    }
    return initialValue;
  });

  const setCachedData = useCallback((value: T) => {
    try {
      const item = {
        data: value,
        timestamp: Date.now()
      };
      localStorage.setItem(key, serializer(item));
      setData(value);
    } catch (error) {
      console.error('Failed to write to localStorage:', error);
    }
  }, [key, serializer]);

  const clearCachedData = useCallback(() => {
    localStorage.removeItem(key);
    setData(initialValue);
  }, [key, initialValue]);

  return [data, setCachedData, clearCachedData] as const;
};

/**
 * 内存缓存Hook
 */
export const useMemoryCache = <T>() => {
  const cacheRef = useRef<Map<string, CacheItem<T>>>(new Map());

  const get = useCallback((key: string): T | null => {
    const item = cacheRef.current.get(key);
    if (item && Date.now() - item.timestamp < item.ttl) {
      return item.data;
    }
    return null;
  }, []);

  const set = useCallback((key: string, value: T, ttl: number = 5 * 60 * 1000): void => {
    cacheRef.current.set(key, {
      data: value,
      timestamp: Date.now(),
      ttl
    });
  }, []);

  const remove = useCallback((key: string): void => {
    cacheRef.current.delete(key);
  }, []);

  const clear = useCallback((): void => {
    cacheRef.current.clear();
  }, []);

  const cleanup = useCallback((): void => {
    const now = Date.now();
    const entries = Array.from(cacheRef.current.entries());
    for (let i = 0; i < entries.length; i++) {
      const [key, item] = entries[i];
      if (now - item.timestamp >= item.ttl) {
        cacheRef.current.delete(key);
      }
    }
  }, []);

  return { get, set, remove, clear, cleanup };
};

/**
 * 请求去重Hook
 */
export const useRequestDeduplication = () => {
  const pendingRequests = useRef<Map<string, Promise<any>>>(new Map());

  const request = useCallback(async <T>(
    key: string,
    requestFn: () => Promise<T>
  ): Promise<T> => {
    // 如果已经有相同的请求在进行中，返回该Promise
    if (pendingRequests.current.has(key)) {
      return pendingRequests.current.get(key);
    }

    const promise = requestFn();
    pendingRequests.current.set(key, promise);

    try {
      const result = await promise;
      return result;
    } finally {
      pendingRequests.current.delete(key);
    }
  }, []);

  return { request };
};

/**
 * 批量缓存Hook
 */
export const useBatchCache = <T>(
  keys: string[],
  fetchFn: (keys: string[]) => Promise<Map<string, T>>,
  options: {
    ttl?: number;
    batchSize?: number;
  } = {}
) => {
  const { ttl = 5 * 60 * 1000, batchSize = 10 } = options;
  const memoryCache = useMemoryCache<T>();
  const [loading, setLoading] = useState(false);

  const getBatch = useCallback(async (keysToFetch: string[]): Promise<Map<string, T>> => {
    const result = new Map<string, T>();
    const keysToRequest: string[] = [];

    // 首先从缓存中查找
    for (const key of keysToFetch) {
      const cached = memoryCache.get(key);
      if (cached) {
        result.set(key, cached);
      } else {
        keysToRequest.push(key);
      }
    }

    // 如果没有需要请求的，直接返回缓存结果
    if (keysToRequest.length === 0) {
      return result;
    }

    try {
      setLoading(true);

      // 批量请求
      for (let i = 0; i < keysToRequest.length; i += batchSize) {
        const batch = keysToRequest.slice(i, i + batchSize);
        const batchResult = await fetchFn(batch);

        // 更新缓存
        for (const [key, value] of batchResult.entries()) {
          memoryCache.set(key, value, ttl);
          result.set(key, value);
        }
      }

      return result;
    } finally {
      setLoading(false);
    }
  }, [fetchFn, memoryCache, ttl, batchSize]);

  const clearBatch = useCallback((keys?: string[]) => {
    if (keys) {
      keys.forEach(key => memoryCache.remove(key));
    } else {
      memoryCache.clear();
    }
  }, [memoryCache]);

  return {
    getBatch,
    clearBatch,
    loading,
    clearAll: memoryCache.clear
  };
};